package cn.sxgan.random;

import cn.sxgan.FilePathConst;
import cn.sxgan.entity.PersonInfo;
import cn.sxgan.utils.DateUtils;
import cn.sxgan.utils.FileUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.fastjson2.JSON;
import lombok.Data;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description: 身份证随机生成工具
 * @Author: sxgan
 * @Date: 2024-08-30 15:32
 * @Version: 1.0
 **/

public class IdCardRandom {
    private static final SecureRandom RANDOM = new SecureRandom();
    private static List<Province> provinces;
    // 提取全部代码及地区
    private static List<County> counties = new ArrayList<>();
    
    // 初始化数据
    static {
        String address = FileUtils.jsonFileToJsonStr(FilePathConst.ADDRESS_FILE_DIR);
        provinces = JSON.parseArray(address, Province.class);
        for (Province province : provinces) {
            String provinceName = province.getName();
            for (City city : province.getCitys()) {
                String cityName = city.getName();
                for (County area : city.getAreas()) {
                    County county = new County();
                    county.setCode(area.getCode());
                    county.setName(provinceName + "-" + cityName + "-" + area.getName());
                    counties.add(county);
                }
            }
        }
    }
    
    /**
     * 生成随机身份证号
     *
     * @return 18位身份证号
     */
    public static String generateRandomID() {
        int startYear = 1970;
        int endYear = 2005;
        return generateRandomID(startYear, endYear);
    }
    
    
    /**
     * 生成随机身份证号
     *
     * @return 18位身份证号
     */
    public static String generateRandomID(int startYear, int endYear) {
        
        StringBuilder idBuilder = new StringBuilder(18);
        // 生成前6位地区码
        County county = counties.get(RANDOM.nextInt(counties.size()));
        String areaCode = county.getCode();
        idBuilder.append(areaCode);
        // 生成7到14位出生日期
        String randomDate = DateUtils.getRandomDate(startYear, endYear, DateUtils.DatePatternEnum.YYYYMMDD);
        idBuilder.append(randomDate);
        // 生成15到17位顺序码
        String sequentialCode = String.format("%03d", RANDOM.nextInt(999));
        idBuilder.append(sequentialCode);
        // 生成第18位校验码
        char checkCode = getCheckCode(idBuilder.toString());
        idBuilder.append(checkCode);
        return idBuilder.toString();
    }
    
    /**
     * 解析证件号获取个人信息
     *
     * @param cardNo 证件号
     * @return 个人信息
     */
    public static PersonInfo getPersonInfoByID(String cardNo) {
        PersonInfo personInfo = new PersonInfo();
        if (cardNo.length() != 18) {
            throw new RuntimeException("身份证位数必须为18位");
        }
        personInfo.setCardNo(cardNo);
        // 拆分
        String areaCode = cardNo.substring(0, 6);
        String birthDate = cardNo.substring(6, 14);
        String sexCode = cardNo.substring(16, 17);
        // 解析地址
        String address = "";
        for (County county : counties) {
            if (county.getCode().equals(areaCode)) {
                address = county.getName();
            }
        }
        if (StringUtils.isBlank(address)) {
            throw new RuntimeException("当前证件号校验失败，地区码有误");
        }
        personInfo.setAddress(address);
        // 解析日期
        Date date = DateUtils.parseStrToDate(birthDate, "yyyyMMdd");
        if (date.after(new Date())) {
            throw new RuntimeException("出生日期不可大于当前日期");
        }
        String birthDateStr = DateUtils.parseDateToStr(date, "yyyy-MM-dd");
        personInfo.setBirthDay(birthDateStr);
        personInfo.setAge(DateUtils.getAge(date));
        personInfo.setSex(Integer.parseInt(sexCode) % 2 == 0 ? "女" : "男");
        personInfo.setPhone(RandomUtils.createPhoneNumber(RandomUtils.OperatorEnum.CHINA_UNICOM));
        return personInfo;
    }
    
    /**
     * 根据前17位身份证号返回校验码
     *
     * @param idWithoutCheckCode
     * @return
     */
    private static char getCheckCode(String idWithoutCheckCode) {
        int[] coefficients = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char[] checkCodeChars = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        int sum = 0;
        for (int i = 0; i < idWithoutCheckCode.length(); i++) {
            sum += coefficients[i] * (idWithoutCheckCode.charAt(i) - '0');
        }
        return checkCodeChars[sum % 11];
    }
    
    public static void exportUserExcel(int size) {
        if (size > 100000 || size < 1) {
            throw new RuntimeException("导出条数最多为100000条，且至少1条");
        }
        File file = new File(FilePathConst.USER_FILE_EXCEL);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            ExcelWriterBuilder write = EasyExcel.write(fileOutputStream, PersonInfo.class);
            List<PersonInfo> list = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                PersonInfo personInfo = getPersonInfoByID(generateRandomID());
                personInfo.setName(RandomUtils.generateChineseName());
                personInfo.setEmail(RandomUtils.createEmail());
                personInfo.setPhone(RandomUtils.createPhoneNumber(RandomUtils.OperatorEnum.CHINA_MOBILE));
                list.add(personInfo);
            }
            write.sheet("个人信息").doWrite(list);
        } catch (IOException e) {
            throw new RuntimeException("个人信息导出失败");
        }
    }
    
    @Data
    static class Province implements Serializable {
        private String name;
        private String code;
        private List<City> citys;
    }
    
    @Data
    static class City implements Serializable {
        private String name;
        private String code;
        private List<County> areas;
    }
    
    @Data
    static class County implements Serializable {
        private String name;
        private String code;
    }
    
    /**
     * 生成数据库插入语句
     */
    static void genMysqlCodeInsert() {
        StringBuffer inserts = new StringBuffer();
        inserts.append("insert into sys_code(config_key, config_value, config_type, description)\n" +
                "values ");
        for (Province province : provinces) {
            String provinceName = province.getName();
            for (City city : province.getCitys()) {
                String cityName = city.getName();
                for (County area : city.getAreas()) {
                    StringBuffer sb = new StringBuffer();
                    sb.append("('" + area.code);
                    sb.append("','" + provinceName + cityName + area.getName());
                    sb.append("', 'code_config', '地区码'),\n");
                    inserts.append(sb.toString());
                }
            }
        }
        System.out.println(inserts.toString());
    }
    
    // public static void main(String[] args) throws InterruptedException {
    //     StopWatch stopWatch = new StopWatch("个人基本信息生成");
    //     stopWatch.start("人员信息生成");
    //     StringBuilder sb = new StringBuilder();
    //     for (int i = 0; i < 50000; i++) {
    //         // PersonInfo personInfo = getPersonInfoByID(generateRandomID(2012, 2016));
    //         PersonInfo personInfo = getPersonInfoByID(generateRandomID());
    //         personInfo.setName(RandomUtils.generateChineseName());
    //         if (personInfo.getName().length() < 2) {
    //             continue;
    //         }
    //         personInfo.setEmail(RandomUtils.createEmail());
    //         personInfo.setPhone(RandomUtils.createPhoneNumber(RandomUtils.OperatorEnum.CHINA_UNICOM));
    //         // log.info();(personInfo.getCardNo() + "," + personInfo.getName() + "," + personInfo.getSex() + "," + personInfo.getBirthDay() + "," + personInfo.getEmail() + "," + personInfo.getPhone() + "," + personInfo.getAddress());
    //         sb.append(personInfo.getCardNo()).append(",").append(personInfo.getName()).append(",").append(personInfo.getSex()).append(",").append(personInfo.getBirthDay()).append(",").append(personInfo.getEmail()).append(",").append(personInfo.getPhone()).append(",").append(personInfo.getAddress()).append("\n");
    //     }
    //     stopWatch.stop();
    //     // log.info();(stopWatch.shortSummary());
    //     stopWatch.start("人员导出至文件");
    //     FileUtils.writeADocument(sb.toString(), FilePathConst.USER_FILE_CSV, false);
    //     stopWatch.stop();
    //
    //     stopWatch.prettyPrint();
    //     // exportUserExcel(200);
    //     StopWatch stopWatch1 = new StopWatch();
    //     stopWatch1.start("task001");
    //     Thread.sleep(2000);
    //     stopWatch1.stop();
    //     log.info(stopWatch1.prettyPrint());
    //     stopWatch1.start();
    //     Thread.sleep(3000);
    //     stopWatch1.stop();
    //     log.info(stopWatch1.prettyPrint());
    // }
}
